home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / os2 / daytime.zip / daytimed.c < prev    next >
C/C++ Source or Header  |  1997-04-16  |  8KB  |  319 lines

  1. /* daytimed.c - daytime and time server daemon
  2.  *
  3.  * for IBM TCP/IP 2.0 for OS/2
  4.  *
  5.  * Author:  Kai Uwe Rommel <rommel@ars.muc.de>
  6.  * Created: Sun Apr 10 1994
  7.  *
  8.  * This code is in the public domain. 
  9.  * Let the author know if you make improvements or fixes, though.
  10.  */
  11.  
  12. static char *rcsid =
  13. "$Id: daytimed.c,v 1.3 1995/08/20 08:15:10 rommel Exp rommel $";
  14. static char *rcsrev = "$Revision: 1.3 $";
  15.  
  16. /*
  17.  * $Log: daytimed.c,v $
  18.  * Revision 1.3  1995/08/20 08:15:10  rommel
  19.  * updated for new emx socket library, IBM compiler
  20.  * fixed minor bugs
  21.  *
  22.  * Revision 1.2  1994/07/17 21:06:45  rommel
  23.  * bug fix: display correct peer address
  24.  *
  25.  * Revision 1.1  1994/07/17 20:46:11  rommel
  26.  * Initial revision
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <getopt.h>
  32. #include <time.h>
  33. #include <string.h>
  34.  
  35. #ifdef OS2
  36. #ifdef __IBMC__
  37. #define BSD_SELECT
  38. #include <types.h>
  39. #include <sys/select.h>
  40. #endif
  41. #include <sys/types.h>
  42. #include <sys/time.h>
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <netdb.h>
  46. #ifdef __EMX__
  47. #define psock_errno perror
  48. #define soclose close
  49. #define sock_init() 0
  50. #endif
  51. #endif
  52.  
  53. typedef enum {TIME = 0, DAYTIME = 1} service;
  54. typedef enum {UDP = 0, TCP = 1} protocol;
  55.  
  56. void send_time(int socket, service serv, protocol proto)
  57. {
  58.   struct sockaddr_in client;
  59.   struct linger linger;
  60.   char buffer[64], *timestr;
  61.   time_t now;
  62.   int bytes, size;
  63.  
  64.   time(&now);
  65.  
  66.   if (serv == DAYTIME)
  67.   {
  68.     timestr = ctime(&now);
  69.     bytes = strlen(timestr) + 1;
  70.   }
  71.   else
  72.   {
  73.     /*
  74.      * The time service returns seconds since 1900/01/01 00:00:00 GMT, not
  75.      * since 1970 as assumed by Unix time_t values.  We need to add 70
  76.      * years' worth of seconds.  Fortunately, RFC 868 tells us that the 
  77.      * daytime value 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT.
  78.      */
  79.     now += 2208988800UL;
  80.  
  81.     now = htonl(now);
  82.     timestr = (char *) &now;
  83.     bytes = sizeof(now);
  84.   }
  85.  
  86.   if (proto == TCP)
  87.   {
  88.     linger.l_onoff = 1;
  89.     linger.l_linger = 10;
  90.  
  91.     if (setsockopt(socket, SOL_SOCKET, SO_LINGER,
  92.            (char *) &linger, sizeof(linger)) < 0)
  93.       psock_errno("setsockopt(SO_LINGER)");
  94.     else
  95.       if (send(socket, timestr, bytes, 0) < 0)
  96.     psock_errno("send()");
  97.  
  98.     size = sizeof(client);
  99.     if (getpeername(socket, (struct sockaddr *) &client, &size) < 0)
  100.       psock_errno("getsockname()");
  101.  
  102.     soclose(socket);
  103.   }
  104.   else
  105.   {
  106.     size = sizeof(client);
  107.     if (recvfrom(socket, buffer, sizeof(buffer), 0, 
  108.          (struct sockaddr *) &client, &size) < 0)
  109.       psock_errno("recvfrom()");
  110.     else
  111.       if (sendto(socket, timestr, bytes, 0, 
  112.          (struct sockaddr *) &client, size) < 0)
  113.     psock_errno("sendto()");
  114.   }
  115.  
  116.   printf("served '%s' request from %s via '%s'\n", 
  117.      serv == DAYTIME ? "daytime" : "time", 
  118.      inet_ntoa(client.sin_addr),
  119.      proto == TCP ? "tcp" : "udp");
  120. }
  121.  
  122. int serve(void)
  123. {
  124.   struct sockaddr_in server, client;
  125.   struct servent *port;
  126.   int tcp_13, tcp_37, udp_13, udp_37, sock_client, length;
  127.   service serv;
  128.   protocol proto;
  129.   
  130.   /* set up daytime (tcp) server */
  131.  
  132.   if ((tcp_13 = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  133.     return psock_errno("socket(daytime tcp)"), 1;
  134.  
  135.   if ((port = getservbyname("daytime", "tcp")) == NULL)
  136.     return psock_errno("getservbyname(daytime tcp)"), 1;
  137.  
  138.   server.sin_family = AF_INET;
  139.   server.sin_port = port -> s_port;
  140.   server.sin_addr.s_addr = INADDR_ANY;
  141.  
  142.   if (bind(tcp_13, (struct sockaddr *) &server, sizeof(server)) < 0)
  143.     return psock_errno("bind(daytime tcp)"), 1;
  144.  
  145.   if (listen(tcp_13, 4) != 0)
  146.     return psock_errno("listen(daytime tcp)"), 1;
  147.  
  148.   /* set up daytime (udp) server */
  149.  
  150.   if ((udp_13 = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
  151.     return psock_errno("socket(daytime udp)"), 1;
  152.  
  153.   if ((port = getservbyname("daytime", "udp")) == NULL)
  154.     return psock_errno("getservbyname(daytime udp)"), 1;
  155.  
  156.   server.sin_family = AF_INET;
  157.   server.sin_port = port -> s_port;
  158.   server.sin_addr.s_addr = INADDR_ANY;
  159.  
  160.   if (bind(udp_13, (struct sockaddr *) &server, sizeof(server)) < 0)
  161.     return psock_errno("bind(daytime udp)"), 1;
  162.  
  163.   /* set up time (tcp) server */
  164.  
  165.   if ((tcp_37 = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  166.     return psock_errno("socket(time tcp)"), 1;
  167.  
  168.   if ((port = getservbyname("time", "tcp")) == NULL)
  169.     return psock_errno("getservbyname(time tcp)"), 1;
  170.  
  171.   server.sin_family = AF_INET;
  172.   server.sin_port = port -> s_port;
  173.   server.sin_addr.s_addr = INADDR_ANY;
  174.  
  175.   if (bind(tcp_37, (struct sockaddr *) &server, sizeof(server)) < 0)
  176.     return psock_errno("bind(time tcp)"), 1;
  177.  
  178.   if (listen(tcp_37, 4) != 0)
  179.     return psock_errno("listen(time tcp)"), 1;
  180.  
  181.   /* set up time (udp) server */
  182.  
  183.   if ((udp_37 = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
  184.     return psock_errno("socket(time udp)"), 1;
  185.  
  186.   if ((port = getservbyname("time", "udp")) == NULL)
  187.     return psock_errno("getservbyname(time udp)"), 1;
  188.  
  189.   server.sin_family = AF_INET;
  190.   server.sin_port = port -> s_port;
  191.   server.sin_addr.s_addr = INADDR_ANY;
  192.  
  193.   if (bind(udp_37, (struct sockaddr *) &server, sizeof(server)) < 0)
  194.     return psock_errno("bind(time udp)"), 1;
  195.  
  196.   /* server loop */
  197.  
  198.   for (;;)
  199.   {
  200.     struct timeval tv;
  201.     fd_set fds;
  202.     int rc, socket;
  203.     
  204.     /* wait for a request */
  205.  
  206.     FD_ZERO(&fds);
  207.     FD_SET(tcp_13, &fds);
  208.     FD_SET(tcp_37, &fds);
  209.     FD_SET(udp_13, &fds);
  210.     FD_SET(udp_37, &fds);
  211.     tv.tv_sec  = 60;
  212.     tv.tv_usec = 0;
  213.  
  214.     if ((rc = select(FD_SETSIZE, &fds, 0, 0, &tv)) < 0)
  215.       return psock_errno("select()"), 1;
  216.     else if (rc == 0)
  217.       continue;
  218.  
  219.     /* determine type and protocol */
  220.       
  221.     if (FD_ISSET(tcp_13, &fds) != 0)
  222.     {
  223.       socket = tcp_13;
  224.       serv = DAYTIME;
  225.       proto = TCP;
  226.     }
  227.     else if (FD_ISSET(tcp_37, &fds) != 0)
  228.     {
  229.       socket = tcp_37;
  230.       serv = TIME;
  231.       proto = TCP;
  232.     }
  233.     else if (FD_ISSET(udp_13, &fds) != 0)
  234.     {
  235.       socket = udp_13;
  236.       serv = DAYTIME;
  237.       proto = UDP;
  238.     }
  239.     else if (FD_ISSET(udp_37, &fds) != 0)
  240.     {
  241.       socket = udp_37;
  242.       serv = TIME;
  243.       proto = UDP;
  244.     }
  245.     else
  246.       continue;
  247.  
  248.     /* and handle it */
  249.  
  250.     if (proto == TCP)
  251.     {
  252.       length = sizeof(client);
  253.       if ((sock_client = accept(socket, 
  254.                 (struct sockaddr *) &client, &length)) == -1)
  255.     return psock_errno("accept()"), 1;
  256.  
  257.       send_time(sock_client, serv, TCP);
  258.     }
  259.     else
  260.       send_time(socket, serv, UDP);
  261.   }
  262.  
  263.   return 0;
  264. }
  265.  
  266. int usage(void)
  267. {
  268.   printf("\nUsage: daytimed [[-dtTU] socket]\n"
  269.          "\n  -d  serve daytime request on socket"
  270.          "\n  -t  serve time request on socket"
  271.          "\n  -T  serve 'tcp' request"
  272.          "\n  -U  serve 'udp' request\n"
  273.      "\nThese options are for use with inetd, the default is to run as a daemon\n");
  274.   return 1;
  275. }
  276.  
  277. int main(int argc, char **argv)
  278. {
  279.   int opt;
  280.   service serv = TIME;
  281.   protocol proto = TCP;
  282.  
  283.   tzset();
  284.  
  285.   if (sock_init())
  286.     return psock_errno("sock_init()"), 1;
  287.  
  288.   if (argc == 1)
  289.     return serve();
  290.  
  291.   while ((opt = getopt(argc, argv, "?TUdt")) != EOF)
  292.     switch (opt)
  293.     {
  294.     case 'd':
  295.       serv = DAYTIME;
  296.       break;
  297.     case 't':
  298.       serv = TIME;
  299.       break;
  300.     case 'T':
  301.       proto = TCP;
  302.       break;
  303.     case 'U':
  304.       proto = UDP;
  305.       break;
  306.     default:
  307.       return usage();
  308.     }
  309.  
  310.   if (optind == argc)
  311.     return usage();
  312.  
  313.   send_time(atoi(argv[optind]), serv, proto);
  314.  
  315.   return 0;
  316. }
  317.  
  318. /* end of daytimed.c */
  319.